|
Connecting custom functions to the report
FastReport has a quite large number of standard functions, which can be used in a report. There also is a possibility to connect your own functions. Connection of functions is performed via the “FastScript” script library's interface, which is included in FastReport (to know more about FastScript, refer to the manual of this library). Let us examine an example of how a procedure and/or a function can be connected. There are two basic ways to perform it: either by using “FastScript” interface, or with help of the “TfrxReport” component's methods. Quantity and type of the connected function's parameters can be different. One cannot transfer parameters of the “Set” and “Record" type, as they are not supported in FastScript. It is required to transfer such parameters as simpler types, for example, to transfer the TRect as X0, Y0, X1, Y1: Integer. See more about process of adding functions with different parameters in the FastScript documentation. Way 1: uses fs_iinterpreter; function TForm1.MyFunc(s: String ; i: Integer): Boolean; begin // necessary logic end; procedure TForm1.MyProc(s: String ); begin // necessary logic end; function TForm1.CallMethod(Instance: TObject; ClassType: TClass; const MethodName: String ; var Params: Variant): Variant; begin else if MethodName = 'MYPROC' then end; fsGlobalUnit.AddMethod('function MyFunc(s: String; i: Integer): Boolean', CallMethod); fsGlobalUnit.AddMethod('procedure MyProc(s: String)', CallMethod); First of all, you should add functions' descriptions via calling fsGlobalUnit.AddMethod. The first parameter is the syntax's description; the second one is a link to the function's handler. Next step would be creation of a handler of the “TfsCallMethodEvent” type and realization of functions' call in it. The handler is the function of a class: TfsCallMethodEvent = function (Instance: TObject; ClassType: TClass; const MethodName: String ; var Params: Variant): Variant of object ; We do not need the “Instance,” and “ClassType” parameters yet. “MethodName” is the name of a function in the upper case; Params is the array of parameters. Way 2: function TForm1.MyFunc(s: String ; i: Integer): Boolean; begin // necessary logic end; procedure TForm1.MyProc(s: String ); begin // necessary logic end; function TForm1.frxReport1UserFunction( const MethodName: String ; var Params: Variant): Variant; begin else if MethodName = 'MYPROC' then end; frxReport1.AddFunction('function MyFunc(s: String; i: Integer): Boolean'); frxReport1.AddFunction('procedure MyProc(s: String)'); This way is a little easier. Functions' descriptions are now added via the “TfrxReport.AddFunction” method with a single parameter. Functions' call is realized in the TfrxReport.OnUserFunction event's handler. Both ways of connection are equivalent. The connected function can be used in the report's script; furthermore, one can refer to it from the objects of the “TfrxMemoView” type. The function is also displayed in the "Data tree" window. In this window functions are split into categories, and thus when you select any function, the hint about this function appears at the bottom of the window. Let us modify the code of our examples to register functions in a separate category, and display the function's description: the first way: fsGlobalUnit.AddMethod('function MyFunc(s: String; i: Integer): Boolean', CallMethod, 'My functions', 'The MyFunc function always returns True'); fsGlobalUnit.AddMethod('procedure MyProc(s: String)', CallMethod, 'My functions', 'The MyProc procedure does not do anything'); the second way: frxReport1.AddFunction('function MyFunc(s: String; i: Integer): Boolean', 'My functions', 'The MyFunc function always returns True'); frxReport1.AddFunction('procedure MyProc(s: String)', 'My functions', 'The MyProc procedure does not do anything'); If you want to register functions in one of the standard categories, use the following categories' names: 'ctString' – string function; 'ctDate' - date/time functions; 'ctConv' - conversion functions; 'ctFormat' - formatting; 'ctMath' - mathematical functions; 'ctOther' - other functions. If a blank category's name is specified, the function is placed to the root of the functions' tree. If you are going to connect a large number of functions, it is recommended to carry out all the logic into a separate unit. Here is an example of such unit: unit myfunctions; interface implementation uses SysUtils, Classes, fs_iinterpreter; type private MethodName: String ; var Params: Variant): Variant; public destructor Destroy; override ; end; var function MyFunc(s: String ; i: Integer): Boolean; begin // necessary logic end; procedure MyProc(s: String ); begin // necessary logic end ; { TFunctions } constructor TFunctions.Create; begin begin AddMethod('function MyFunc(s: String; i: Integer): Boolean', CallMethod, 'My functions', 'The MyFunc function always returns True'); AddMethod('procedure MyProc(s: String)', CallMethod, 'My functions', 'The MyProc procedure does not do anything''); AddedBy := nil ; end; end; destructor TFunctions.Destroy; begin inherited; end; function TFunctions.CallMethod(Instance: TObject; ClassType: TClass; const MethodName: String ; var Params: Variant): Variant; begin else if MethodName = 'MYPROC' then end; initialization finalization end. |